package com.umeox.quranplayer.ui

import android.annotation.SuppressLint
import android.app.KeyguardManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.*
import android.text.TextUtils
import android.text.format.DateUtils
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.SeekBar
import android.widget.TextView
import androidx.constraintlayout.widget.Group
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.umeox.moto.common.log.Logger
import com.umeox.moto.watch.themes.app.ThemeAppCompatActivity
import com.umeox.moto.watch.themes.widget.ProgressView
import com.umeox.quranplayer.R
import com.umeox.quranplayer.bean.QuranChallenge
import com.umeox.quranplayer.db.AppDatabase
import com.umeox.quranplayer.db.model.ChallengeRecord
import com.umeox.quranplayer.event.ChallengeEvent
import com.umeox.quranplayer.repository.*
import com.umeox.quranplayer.repository.model.QuranAudioBean
import com.umeox.quranplayer.viewmodel.TimerViewModel
import com.umeox.quranplayer.widgets.ChallengeResultDialog
import com.umeox.watch.moto.dataservice.proxy.PullApiClientProxy
import com.yc.music.config.MusicConstant
import com.yc.music.inter.OnPlayerEventListener
import com.yc.music.model.AudioBean
import com.yc.music.service.PlayService
import com.yc.music.tool.BaseAppHelper
import com.yc.music.utils.MusicSpUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.StringBuilder
import java.util.*
import kotlin.math.abs

class ChallengeActivity : ThemeAppCompatActivity(), View.OnClickListener, OnPlayerEventListener {

    /**
     * 播放位置(秒)
     */
    private var playPosition = 0


    private var tvTitleAr: TextView? = null
    private var tvTitleEn: TextView? = null
    private var tvCurrentTime: TextView? = null
    private var sbProgress: SeekBar? = null
    private var tvTotalTime: TextView? = null
    private var ivPlay: ImageView? = null
    private var ivVolume: ImageView? = null
    private var pbLoadFile: ProgressBar? = null

    private lateinit var mTimeProgressView: ProgressView
    private lateinit var mRewardsTv: TextView

    private var audioBean: QuranAudioBean? = null

    private lateinit var mPlayServiceConnection: PlayServiceConnection

    private var mLastProgress = 0

    private var isDraggingProgress = false

    private var mCurrentChallenge: QuranChallenge? = null

    private lateinit var mTimerViewModel: TimerViewModel

    private var mTotalTime: Int = 0

    private var mCurrentChallengeRecord: ChallengeRecord? = null

    private var mPreCompleteTotalSec: Int = 0

    private var isStart: Boolean = false//时间计时器是否已经启动标记

    private var wakeLock: PowerManager.WakeLock? = null
    private var kl: KeyguardManager.KeyguardLock? = null

    private var challengeResultDialog: ChallengeResultDialog? = null
    private val MSG_FINISH: Int = 0x10
    private val mHandler: Handler = Handler { msg ->
        if (msg.what == MSG_FINISH) {
            challengeResultDialog?.dismiss()
        }
        false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_challenge)

        mCurrentChallenge = intent.getParcelableExtra("challenge_data")

        if (mCurrentChallenge != null) {
            mCurrentChallengeRecord = AppDatabase.get().challengeRecordDao()
                .queryCurrentChallengeRecord(
                    com.umeox.moto.common.utils.DateUtils.getTodayMillis(),
                    mCurrentChallenge!!.id,
                    mCurrentChallenge!!.chapterIndex
                )
        }

        Logger.e("mCurrentChallenge=$mCurrentChallenge,mCurrentChallengeRecord=$mCurrentChallengeRecord")


        if (mCurrentChallengeRecord != null) {
            mPreCompleteTotalSec = mCurrentChallengeRecord!!.duration
        }

        startCheckService(window.decorView)
        mTimerViewModel = ViewModelProvider(this)[TimerViewModel::class.java]
        EventBus.getDefault().register(this)

        initView()
        registerViewModelObserver()
        initListener()
    }

    private fun registerViewModelObserver() {

        mTimerViewModel.mElapsedTimeLiveData.observe(this) {
            mTotalTime = it.toInt() + mPreCompleteTotalSec
            Logger.e("mTotalTime->$mTotalTime")
            if ((it % 3) == 0L) {
                if (mTimeProgressView.progress < 1.0f) {
                    mTimeProgressView.progress = mTotalTime / (mCurrentChallenge!!.duration * 60F)
                }
            }
        }
    }

    private fun initView() {
        tvTitleAr = findViewById(R.id.tv_title_ar)
        tvTitleEn = findViewById(R.id.tv_title_en)
        tvCurrentTime = findViewById(R.id.tv_current_time)
        sbProgress = findViewById(R.id.sb_progress)
        tvTotalTime = findViewById(R.id.tv_total_time)

        ivPlay = findViewById(R.id.iv_play)
        ivVolume = findViewById(R.id.iv_volume)
        pbLoadFile = findViewById(R.id.pb_load_file)

        mRewardsTv = findViewById(R.id.reward_tv)
        mTimeProgressView = findViewById(R.id.time_progress)
        mTimeProgressView.progress = mPreCompleteTotalSec / (mCurrentChallenge!!.duration * 60F)

        mRewardsTv.text = "+${mCurrentChallenge?.rewardValue}"
    }

    private fun initListener() {
        ivPlay?.setOnClickListener(this)
        ivVolume?.setOnClickListener(this)

        val onSeekBarChangeListener: SeekBar.OnSeekBarChangeListener =
            object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                    if (seekBar === sbProgress) {
                        if (abs(progress - mLastProgress) >= DateUtils.SECOND_IN_MILLIS) {
                            tvCurrentTime!!.text = formatTime(progress.toLong())
                            mLastProgress = progress
                        }
                    }
                }

                override fun onStartTrackingTouch(seekBar: SeekBar) {
                    if (seekBar === sbProgress) {
                        isDraggingProgress = true
                    }
                }

                /**
                 * 通知用户已结束触摸手势,触摸结束时调用
                 * @param seekBar               seekBar
                 */
                override fun onStopTrackingTouch(seekBar: SeekBar) {
                    if (seekBar === sbProgress) {
                        isDraggingProgress = false

                        if (BaseAppHelper.get().musicService.isPlaying || BaseAppHelper.get().musicService.isPausing) {
                            val progress = seekBar.progress
                            BaseAppHelper.get().musicService.seekTo(progress)
                        } else {
                            seekBar.progress = 0
                        }
                    }
                }
            }
        sbProgress!!.setOnSeekBarChangeListener(onSeekBarChangeListener)
    }

    @SuppressLint("SetTextI18n")
    private fun setViewData(playingMusic: QuranAudioBean) {
        tvTitleAr!!.text = playingMusic.nameAR
        tvTitleEn!!.text = playingMusic.nameEN

        tvCurrentTime!!.text = formatTime(playPosition.toLong())
        sbProgress!!.progress = playPosition
        sbProgress!!.secondaryProgress = 0
        sbProgress!!.max = playingMusic.duration.toInt()

        tvTotalTime!!.text = formatTime(playingMusic.duration)
    }

    private fun initPlayServiceListener() {
        if (BaseAppHelper.get().musicService == null) {
            return
        }
        BaseAppHelper.get().musicService.addOnPlayEventListener(this)
//        val musicService = BaseAppHelper.get().musicService
//        val playing = musicService.isPlaying
//        ivPlay!!.isSelected = playing || musicService.isPreparing
    }


    override fun onDestroy() {
        super.onDestroy()
        releaseLock()
        EventBus.getDefault().unregister(this)
        if (::mPlayServiceConnection.isInitialized) {
            BaseAppHelper.get().musicService?.removeOnPlayEventListener(this)
            BaseAppHelper.get().musicService?.quit()
            mTimerViewModel.end()

            saveOrUpdateChallengeRecord()
        }
    }

    private fun saveOrUpdateChallengeRecord() {
        if (mCurrentChallengeRecord != null) {
            mCurrentChallengeRecord!!.duration = mTotalTime
            AppDatabase.get().challengeRecordDao().update(mCurrentChallengeRecord!!)
        } else {
            val challengeRecord = ChallengeRecord()
            challengeRecord.quranLearnId = mCurrentChallenge!!.id
            challengeRecord.chapterIndex = mCurrentChallenge!!.chapterIndex
            challengeRecord.duration = mTotalTime
            challengeRecord.targetDuration = mCurrentChallenge!!.duration
            challengeRecord.rewardValue = mCurrentChallenge!!.rewardValue
            challengeRecord.todayMillis = com.umeox.moto.common.utils.DateUtils.getTodayMillis()
            challengeRecord.deadLine = mCurrentChallenge!!.deadline

            AppDatabase.get().challengeRecordDao().save(challengeRecord)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    fun onChallengeEvent(challengeEvent: ChallengeEvent) {
        wakeUpAndUnlock()
        //挑战时长已达标
        //1.更新本地记录
        if (mCurrentChallengeRecord != null) {
            var needUpload = false
            mCurrentChallengeRecord!!.duration = mTotalTime
            if (System.currentTimeMillis() <= com.umeox.moto.common.utils.DateUtils.formatDateToTime(
                    mCurrentChallengeRecord!!.deadLine
                )
            ) {//当前时间小于截止时间 已完成挑战
                mCurrentChallengeRecord!!.finishTime =
                    com.umeox.moto.common.utils.DateUtils.formatDateTime(
                        System.currentTimeMillis(),
                        "yyyyMMdd'T'HHmmssZ"
                    )
                mCurrentChallengeRecord!!.isComplete = true
                needUpload = true
            }
            AppDatabase.get().challengeRecordDao().update(mCurrentChallengeRecord!!)
            if (needUpload) {
                challengeResultDialog =
                    ChallengeResultDialog(
                        this@ChallengeActivity,
                        mCurrentChallenge!!,
                    )
                challengeResultDialog?.show()
                mHandler.sendEmptyMessageDelayed(MSG_FINISH, 5000)
                uploadChallengeRecord(mCurrentChallengeRecord!!)
            }
        } else {
            var needUpload = false
            val challengeRecord = ChallengeRecord()
            challengeRecord.quranLearnId = mCurrentChallenge!!.id
            challengeRecord.chapterIndex = mCurrentChallenge!!.chapterIndex
            challengeRecord.duration = mTotalTime
            challengeRecord.targetDuration = mCurrentChallenge!!.duration
            challengeRecord.rewardValue = mCurrentChallenge!!.rewardValue
            challengeRecord.todayMillis = com.umeox.moto.common.utils.DateUtils.getTodayMillis()
            challengeRecord.deadLine = mCurrentChallenge!!.deadline
            if (System.currentTimeMillis() <= com.umeox.moto.common.utils.DateUtils.formatDateToTime(
                    mCurrentChallenge?.deadline
                )
            ) {//当前时间小于截止时间 已完成挑战
                challengeRecord.finishTime = com.umeox.moto.common.utils.DateUtils.formatDateTime(
                    System.currentTimeMillis(),
                    "yyyyMMdd'T'HHmmssZ"
                )
                challengeRecord.isComplete = true
                needUpload = true
            }

            AppDatabase.get().challengeRecordDao().save(challengeRecord)
            if (needUpload) {
                challengeResultDialog =
                    ChallengeResultDialog(
                        this@ChallengeActivity,
                        mCurrentChallenge!!,
                    )
                challengeResultDialog?.show()
                mHandler.sendEmptyMessageDelayed(MSG_FINISH, 5000)
                uploadChallengeRecord(challengeRecord)
            }
        }
    }


    private fun wakeUpAndUnlock() {
        if (kl == null) {
            val km = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
            kl = km.newKeyguardLock("unLock")
        }
        //解锁
        kl?.disableKeyguard()
        if (wakeLock == null) {
            val pm = getSystemService(POWER_SERVICE) as PowerManager
            wakeLock = pm.newWakeLock(
                PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.FULL_WAKE_LOCK,
                javaClass.simpleName
            )
        }
        // 点亮亮屏
        wakeLock?.acquire()
    }

    private fun releaseLock() {
        if (wakeLock != null) {
            try {
                wakeLock?.release()
            } catch (th: Throwable) {
                Logger.e("Releasing wakelock failed:$th")
            }
        } else {
            Logger.e("Wakelock reference is null")
        }
    }


    private fun uploadChallengeRecord(challengeRecord: ChallengeRecord) {
        val result = PullApiClientProxy.fetchBinder().uploadQuranChallengeRecord(
            challengeRecord.quranLearnId,
            challengeRecord.chapterIndex,
            challengeRecord.finishTime,
            challengeRecord.duration / 60,
            challengeRecord.rewardValue
        )

        if (result) {
            challengeRecord.isUpload = true
            AppDatabase.get().challengeRecordDao().update(challengeRecord)
        }
    }

    private fun onChangeImpl(music: QuranAudioBean?) {
        if (music == null) {
            return
        }
        tvTitleAr!!.text = music.nameAR
        tvTitleEn!!.text = music.nameEN

        tvCurrentTime!!.text = formatTime(playPosition.toLong())
        sbProgress!!.max = music.duration.toInt()
        sbProgress!!.progress = 0
        tvTotalTime!!.text = formatTime(music.duration)

        ivPlay!!.isSelected =
            BaseAppHelper.get().musicService.isPlaying || BaseAppHelper.get().musicService.isPreparing
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.iv_play -> {
                BaseAppHelper.get().musicService?.playPause()
            }
            R.id.iv_volume -> {
                startActivity(Intent(this, VolumeSettingActivity::class.java))
            }
            else -> {}
        }
    }

    override fun onChange(music: AudioBean?) {
        if (music is QuranAudioBean) {
            onChangeImpl(music)
        }
    }

    override fun onPlayerStart() {
        Logger.e("========onPlayerStart========")
        ivPlay!!.isSelected = true
        //播完再次播放也会触发
        if (!isStart && mTimeProgressView.progress < 1.0f) {
            mTimerViewModel.start(mCurrentChallenge?.duration?.times(60)?.toLong()!! - mPreCompleteTotalSec)
            isStart = true
        }
    }

    override fun onPlayerPause() {
        Logger.e("========onPlayerPause========")
        ivPlay!!.isSelected = false
        mTimerViewModel.pause()
        mPreCompleteTotalSec = mTotalTime
        isStart = false
    }

    override fun onCompletion() {
    }

    override fun onUpdateProgress(progress: Int) {
        val progressCompat = if (progress < 1000) {
            0
        } else {
            progress
        }
        sbProgress!!.progress = progressCompat
    }

    override fun onBufferingUpdate(percent: Int) {
    }

    override fun onTimer(remain: Long) {
    }

    override fun onDuration(totalDuration: Int) {
    }

    /**
     * 检测服务
     */
    private fun startCheckService(rootView: View) {
        startService()
        rootView.postDelayed({ bindService() }, 500)
    }

    /**
     * 开启服务
     */
    private fun startService() {
        val intent = Intent(this, PlayService::class.java)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent)
        } else {
            startService(intent)
        }
    }

    /**
     * 绑定服务
     * 注意对于绑定服务一定要解绑
     */
    private fun bindService() {
        val intent = Intent()
        intent.setClass(mContext, PlayService::class.java)
        mPlayServiceConnection = PlayServiceConnection()
        mContext.bindService(intent, mPlayServiceConnection, Context.BIND_AUTO_CREATE)
    }

    /**
     * 构建数据集合
     */
    fun buildLocalAudioListData() {
        pbLoadFile?.visibility = View.VISIBLE
        lifecycleScope.launchWhenCreated {
            QuranAudioManager.buildChallengeQuranAudioBean(mCurrentChallenge?.chapterIndex!!)
            withContext(Dispatchers.Main) {
                pbLoadFile?.visibility = View.GONE
                audioBean = QuranAudioManager.currentChallengeQuranAudioBean
                val musicList = BaseAppHelper.get().musicList
                musicList.clear()
                musicList.add(QuranAudioManager.currentChallengeQuranAudioBean)

                val helper = BaseAppHelper.get()
                helper.playService.play(helper.musicList.indexOf(audioBean))
                setViewData(audioBean!!)
            }
        }
    }

    private fun formatTime(milliseconds: Long): String {
        if (milliseconds <= 0 || milliseconds >= 24 * 60 * 60 * 1000) {
            return "00:00"
        }
        val totalSeconds = milliseconds / 1000
        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60
        val hours = totalSeconds / 3600
        val stringBuilder = StringBuilder()
        val mFormatter = Formatter(stringBuilder, Locale.ENGLISH)
        return if (hours > 0) {
            mFormatter.format("%03d:%02d", minutes, seconds).toString()
        } else {
            mFormatter.format("%03d:%02d", minutes, seconds).toString()
        }
    }

    inner class PlayServiceConnection : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            BaseAppHelper.get().playService = (service as PlayService.PlayBinder).service
            lifecycleScope.launch(Dispatchers.Main) {
                initPlayServiceListener()
                buildLocalAudioListData()
            }
        }

        override fun onServiceDisconnected(name: ComponentName) {

        }

    }


}